﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OAuthAccess;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Xml.Linq;

namespace TwitpicUploadByOAuthEchoSample
{
    class Program
    {
        [STAThread()]
        static void Main(string[] args)
        {
            //Twitter don't support 100Continue.
            ServicePointManager.Expect100Continue = false;

            /*
             * This Sample is upload image to Twitpic by OAuthEcho.
             * When you upload image to Twitpic by OAuthEcho, you access Twitpic by using OAuthHeader for Twitter. 
             * if you rewrite the following 3 strings,this sample will be available. 
             */

            string twitpicApikey = "twitpic api key";
            string twitterConsumerKey = "twitter consumer key";
            string twitterConsumerSecret = "twitter consumer secret";

            #region Until Access Token is obtained

            /*
             * Uses OAuthAuthorizationService class until Access Token is obtained.
             */

            Consumer consumer = new Consumer(
                twitterConsumerKey,
                twitterConsumerSecret);

            //Get Request Token
            RequestToken requestToken = OAuthAuthorizationService.GetRequestToken(
                consumer,
                "http://twitter.com/oauth/request_token",
                "http://twitter.com/",
                HttpMethodType.Get).Token as RequestToken;

            //It is necessary you have authenticated to user. 
            Process.Start(OAuthAuthorizationService.GetUserAuthorizationURL(
                "http://twitter.com/oauth/authorize",
                requestToken));

            //You have inputted to user.
            Console.Out.WriteLine("Please input verify...");

            string verifier = Console.In.ReadLine().TrimEnd('\r', '\n');

            //Get AccessToken

            TokenResponse accessTokenResponse = OAuthAuthorizationService.GetAccessToken(
                consumer,
                "http://twitter.com/oauth/access_token",
                "http://twitter.com/",
                requestToken,
                verifier,
                HttpMethodType.Post);

            AccessToken accessToken = accessTokenResponse.Token as AccessToken;

            string user_id = (from p in accessTokenResponse.AdditionalParameters
                              where p.Key == "user_id"
                              select p).First().Value;

            string screen_name = (from p in accessTokenResponse.AdditionalParameters
                                  where p.Key == "screen_name"
                                  select p).First().Value;

            Console.WriteLine("Screen_Name : " + screen_name);

            #endregion

            #region Choose Image that you want upload
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            ofd.Title = "Choose Image that upload to Twitpic";
            ofd.Filter = "Supported File Format|*.jpg;*.jpeg;*.gif;*.png|JPEG File|*.jpg;*.jpeg|GIF File|*.gif|PNG File|*.png";

            if (ofd.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            string path = ofd.FileName;
            #endregion

            string boundary = Guid.NewGuid().ToString();

            string header = "--" + boundary;
            string footer = Environment.NewLine + "--" + boundary + "--";

            string responseText = null;

            byte[] fileBinary = File.ReadAllBytes(path);

            StringBuilder headers = new StringBuilder();
            headers.AppendLine(header);
            headers.AppendLine("Content-Disposition: form-data; name=\"key\"");
            headers.AppendLine();
            headers.AppendLine(twitpicApikey);
            headers.AppendLine(header);

            headers.AppendLine("Content-Disposition: form-data; name=\"message\"");
            headers.AppendLine();
            headers.AppendLine(string.Empty);
            headers.AppendLine(header);

            headers.AppendLine("Content-Disposition: form-data; name=\"media\"; filename=\"" + Path.GetFileName(path) + "\"");
            headers.AppendLine("Content-Type: application/octet-stream");
            headers.AppendLine("Content-Transfer-Encoding: binary");
            headers.AppendLine();

            HttpWebRequest req = WebRequest.Create("http://api.twitpic.com/2/upload.xml") as HttpWebRequest;

            req.ContentType = "multipart/form-data; boundary=" + boundary;

            #region Sets Header for OAuth

            var tempRequest =
                 OAuthRequest.Create(consumer, accessToken)
                .SetUrl("https://api.twitter.com/1/account/verify_credentials.json")
                .SetHttpMethod(HttpMethodType.Get)
                .SetRealm("http://api.twitter.com/")
                .CommitRequest();

            req.Headers["X-Verify-Credentials-Authorization"] = tempRequest.AuthorizationHeader;

            req.Headers["X-Auth-Service-Provider"] = "https://api.twitter.com/1/account/verify_credentials.json";

            #endregion

            req.Method = "POST";

            byte[] headersBytes = Encoding.UTF8.GetBytes(headers.ToString());
            byte[] footerBytes = Encoding.UTF8.GetBytes(footer);

            req.ContentLength = headersBytes.Length + fileBinary.Length + footerBytes.Length;

            using (Stream s = req.GetRequestStream())
            {
                s.Write(headersBytes, 0, headersBytes.Length);
                s.Write(fileBinary, 0, fileBinary.Length);
                s.Write(footerBytes, 0, footerBytes.Length);
                s.Flush();
                s.Close();

                using (WebResponse response = req.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        responseText = reader.ReadToEnd();
                    }
                }
            }


            XElement result = XElement.Parse(responseText);

            Process.Start(result.Element("url").Value.ToString());
        }
    }
}
